package za.co.chaotik.tron.maps;

import java.util.ArrayList;
import java.util.List;

import za.co.chaotik.tron.AbstractMap;
import za.co.chaotik.tron.Cycle;
import za.co.chaotik.tron.Position;
import za.co.chaotik.tron.exceptions.UnsupportedNumberOfPlayersException;

public class RectangularMap extends AbstractMap {
	public RectangularMap(int width, int height, int numPlayers) {
		super(width, height, numPlayers);
		
		// Create map
		this.positions = new ArrayList<List<Position>>(getHeight());
		for (int rows = 0; rows < getHeight(); rows++) {
			ArrayList<Position> row = new ArrayList<Position>(getWidth());
			this.positions.add(row);
			
			for (int cols = 0; cols < getWidth(); cols++) {
				row.add(new Position(cols, rows));
			}
		}
	}

	@Override
	public void init() throws UnsupportedNumberOfPlayersException {
		// Place cycles	
		if (players.size() != 2) {
			// Invalid number of players for this type of map
			throw new UnsupportedNumberOfPlayersException("RectangularMap only supports 2 player games.");
		}
		
		for (int i = 0; i < players.size(); i++) {
			int x = i * (getWidth() - 1);
			int y = getHeight() / 2;
			
			Cycle cycle = cycles.get(i);
			
			this.addCycle(cycle, getPosition(x, y));
		}
	}
	
	@Override
	public List<Position> getValidMoves(Cycle cycle) {
		List<Position> positions = new ArrayList<Position>();
		List<Position> validMoves = new ArrayList<Position>();

		int x = cycle.getX();
		int y = cycle.getY();
		
		positions.add(this.getPosition(x - 1, y));
		positions.add(this.getPosition(x + 1, y));
		positions.add(this.getPosition(x, y - 1));
		positions.add(this.getPosition(x, y + 1));
		
		for (Position pos : positions) {
			if (isValidFor(pos, cycle)) {
				validMoves.add(pos);
			}
		}
		
		return validMoves;
	}
	
	private boolean isValidFor(Position pos, Cycle cycle) {
		// Position must be on the map
		if (pos == null) {
			return false;
		}
		
		// Cycle may not move backwards
		List<Position> cycleMoves = moves.get(cycle.getOwner());
		
		if ((cycleMoves.size() > 1) && (cycleMoves.get(cycleMoves.size() - 2).equals(pos))) {
			return false;
		}
		
		return true;
	}
}
